package ua.kpi.flats.service.impl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import ua.kpi.flats.dao.MeetingDao;
import ua.kpi.flats.entity.Meeting;
import ua.kpi.flats.service.MeetingService;

@Service("meetingService")
public class MeetingServiceImpl implements MeetingService {
	private Logger logger = LoggerFactory.getLogger(MeetingServiceImpl.class);
	
	private MeetingDao meetingDao;
	
	@PreAuthorize("hasRole('ROLE_REALTOR')")
	@Transactional(propagation = Propagation.REQUIRES_NEW,
			       isolation = Isolation.READ_COMMITTED)
	public Map<String,Object> create(Meeting meeting) {
		Map<String,Object> result = new HashMap<String,Object>();
		result.put("success", true);
		try {			
			meetingDao.create(meeting);
			return result;
		} catch (InvalidDataAccessResourceUsageException e) {
			logger.error("Try to add same meeting", e);
			result.put("copy", true);
			return result;
		} catch (DataAccessException e) {
			logger.error("Cant add meeting", e);
			result.put("error", true);
			return result;
		} 
	}
	
	@Transactional(readOnly = true,
			       propagation = Propagation.REQUIRES_NEW,
			       isolation = Isolation.READ_COMMITTED) 
	public List<Meeting> getMeetings(long appId) {
		try {
			return meetingDao.getMeetings(appId);
		} catch (DataAccessException e) {
			logger.error("Cant load meetings by app with id " + appId, e);
			return null;
		}
	}
	
	@Transactional(propagation = Propagation.REQUIRES_NEW,
			       isolation = Isolation.READ_COMMITTED)
    public boolean delete(Meeting meeting) {
		try {
			meetingDao.delete(meeting);
			return true;
		} catch (DataAccessException e) {
			logger.error("Cant delete meeting with id " + meeting.getId(), e);
			return false;
		}
	}
	
	@Transactional(propagation = Propagation.REQUIRES_NEW,
			       isolation = Isolation.READ_COMMITTED)
    public boolean finish(Meeting meeting) {
		try {
			meetingDao.finish(meeting);
			return true;
		} catch (DataAccessException e) {
			logger.error("Cant finish meeting with id " + meeting.getId(), e);
			return false;
		}
	}
	
	@Autowired
	public void setMeetingDao(MeetingDao meetingDao) {
		this.meetingDao = meetingDao;
	}

}
